package cn.iocoder.yudao.framework.mybatis.autotable.creator;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.comments.JavadocComment;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;

public class JavadocExtractor {
    
    /**
     * 提取类的Javadoc注释
     * @param clazz 目标类
     * @return 清理后的Javadoc注释
     */
    public static String extractClassJavadoc(Class<?> clazz) {
        try {
            CompilationUnit cu = parseSourceFile(clazz);
            if (cu == null) return "";
            
            // 查找类声明
            Optional<ClassOrInterfaceDeclaration> classDecl = cu.getClassByName(clazz.getSimpleName());
            if (classDecl.isPresent()) {
                return classDecl.get().getJavadocComment()
                        .map(javadoc -> cleanJavadoc(javadoc.parse().toText()))
                        .orElse("");
            }
        } catch (Exception e) {
            // 忽略异常
        }
        return "";
    }
    
    /**
     * 提取字段的Javadoc注释
     * @param clazz 目标类
     * @param fieldName 字段名
     * @return 清理后的Javadoc注释
     */
    public static String extractFieldJavadoc(Class<?> clazz, String fieldName) {
        try {
            CompilationUnit cu = parseSourceFile(clazz);
            if (cu == null) return "";
            
            // 查找类声明
            Optional<ClassOrInterfaceDeclaration> classDecl = cu.getClassByName(clazz.getSimpleName());
            if (!classDecl.isPresent()) return "";
            
            // 创建字段访问器
            FieldVisitor visitor = new FieldVisitor(fieldName);
            visitor.visit(cu, null);
            return visitor.getJavadoc();
        } catch (Exception e) {
            // 忽略异常
        }
        return "";
    }
    
    /**
     * 解析类的源文件
     */
    private static CompilationUnit parseSourceFile(Class<?> clazz) throws Exception {
        // 获取类所在的资源路径
        String resourcePath = clazz.getName().replace('.', '/') + ".class";
        URL resource = clazz.getClassLoader().getResource(resourcePath);
        if (resource == null) return null;
        String path = resource.getPath();
        path = path.replace("/target/classes/","/src/main/java/");
        path = path.replace(".class",".java")        ;

        File sourceFile = new File(path);
        if (sourceFile.exists()) {
            try (FileInputStream in = new FileInputStream(sourceFile)) {
                JavaParser javaParser = new JavaParser();
                ParseResult<CompilationUnit> parseResult = javaParser.parse(in);
                if (parseResult.isSuccessful() && parseResult.getResult().isPresent()) {
                    return parseResult.getResult().get();
                }
            }
        }
        return null;
    }
    
    /**
     * 清理Javadoc注释
     * 1. 移除开头的 /** 和结尾的 * /
     * 2. 移除每行开头的 * 和空格
     * 3. 替换多个连续空格为单个空格
     */
    private static String cleanJavadoc(String javadoc) {
        if (javadoc == null || javadoc.isEmpty()) return "";
        
        // 移除开头的 /** 和结尾的 * /
        String cleaned = javadoc.replaceFirst("^/\\*\\*", "")
                               .replaceFirst("\\*/$", "")
                               .trim();
        
        // 移除每行开头的 * 和空格
        cleaned = cleaned.replaceAll("\n\\s*\\*\\s*", "\n");
        
        // 替换多个连续空格为单个空格
        cleaned = cleaned.replaceAll("\\s+", " ");
        
        // 移除HTML标签
        cleaned = cleaned.replaceAll("<[^>]+>", "");
        
        return cleaned.trim();
    }
    
    /**
     * 字段访问器，用于查找特定字段的Javadoc
     */
    private static class FieldVisitor extends VoidVisitorAdapter<Void> {
        private final String targetFieldName;
        private String javadoc = "";
        
        public FieldVisitor(String fieldName) {
            this.targetFieldName = fieldName;
        }
        
        @Override
        public void visit(FieldDeclaration n, Void arg) {
            super.visit(n, arg);
            
            // 检查字段名是否匹配
            if (n.getVariables().stream().anyMatch(v -> v.getNameAsString().equals(targetFieldName))) {
                javadoc = n.getJavadocComment()
                          .map(jc -> cleanJavadoc(jc.parse().toText()))
                          .orElse("");
            }
        }
        
        public String getJavadoc() {
            return javadoc;
        }
    }
}